home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / utilities / cli / bindnames.lha / BindNames / BindNames.c next >
Encoding:
C/C++ Source or Header  |  1994-08-18  |  16.8 KB  |  634 lines

  1. /* ====================================================================== */
  2.  
  3. /*    BindNames.c by Dave Haynie
  4.  
  5.     This is a simple utility to remove some of the drudgery of program
  6.     installation.  Instead of having to edit a Startup-Sequence for
  7.     every logical name that must be used by a new program, this lets
  8.     names be block-allocated.  The BindNames program looks for files
  9.     in the SYS:Names directory.  Each of these files contains any number
  10.     of lines of the form:
  11.     
  12.         Name:    Path
  13.     
  14.     Where "Name" is the logical name we're assigning, "Path" is the
  15.     path name we're making equivalent.  
  16.  
  17.     improved by Jan Rembser 8.8.94:
  18.         -multiple assigns ("Assign ADD")
  19.         -for each assign one single path could be marked with a #,
  20.         this path will be assigned first
  21.         Bsp: Libs: sys:libs,sys:classes,sys:libs/libs2#
  22.  
  23.             it results in 'assign libs: sys:libs/libs2 sys:libs sys:classes'
  24.             and not in    'assign libs: sys:libs sys:classes sys:libs/libs2'
  25.  
  26.         -extended verbosity with VVERBOSE (VV) means "very verbose"
  27. */
  28.  
  29. #include <exec/types.h>
  30. #include <exec/memory.h>    
  31. #include <exec/libraries.h>    
  32. #include <dos/dos.h>
  33. #include <dos/dostags.h>
  34. #include <libraries/dosextens.h>
  35. #include <proto/all.h>
  36. #include <stdio.h>
  37. #include <ctype.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40.  
  41. /* ====================================================================== */
  42.  
  43. /* Macros */
  44.  
  45. static char version[] = "\0$VER: BindNames 3.70 (17.08.94)";
  46. #define    HELLO        "BindNames by Dave Haynie, Dan Barrett and Jan Rembser"
  47.  
  48. #define VERBOSE if (verbose) printf
  49. #define VVERBOSE if (veryverbose) printf
  50.  
  51. #define CADDR(x)    ((BPTR)(((ULONG)x)>>2))
  52. #define NAMEDIR        "SYS:Names"
  53. #define NAMEDIRVAR    "BindNamesDirectory"
  54. #define CopyStr(s)    strcpy(malloc(strlen(s)+1),s)
  55. #define CatStr(s1,s2) strcat(strcat(strcpy(malloc(strlen(s1)+strlen(s2)+3),s1),","),s2)
  56. #define CatCom(s1,s2) strcat(strcat(strcpy(malloc(strlen(s1)+strlen(s2)+3),s1),s2),":")
  57. #define FreeStr(s)    free(s)
  58.  
  59. /* The "-rr" option doesn't like NewList, bit it's real simple.  WHEN can
  60.     we have inline functions.... */
  61.  
  62. #define NewList(l)    { (l)->lh_Head     = (struct Node *)&(l)->lh_Tail; \
  63.                 (l)->lh_TailPred = (struct Node *)&(l)->lh_Head; \
  64.                 (l)->lh_Tail     = NULL;            \
  65.             }
  66.  
  67. /* ====================================================================== */
  68.  
  69. /* Global variables */
  70.  
  71. extern struct Library *SysBase;   /* Use this to check the OS version number */
  72. extern struct DosLibrary *DosBase = NULL;
  73. struct DosInfo *info = NULL;
  74. struct DeviceList *lastdev;
  75. BPTR namelock = NULL;
  76. BOOL     verbose = FALSE, veryverbose = FALSE, test = FALSE, adding = TRUE;
  77. struct FileInfoBlock *fileinfo = NULL;
  78. struct TagItem STags[4];
  79.  
  80. /* ====================================================================== */
  81.  
  82. /* Return the name of the BindNames name directory. */
  83.  
  84. char *NameDir(char *argdir)
  85. {
  86.     char *dir;
  87.     static char default_dir[] = NAMEDIR;
  88.  
  89.     if (((dir = getenv(NAMEDIRVAR)) == NULL) && (!argdir))
  90.         return(default_dir);
  91.     else if (argdir) dir = argdir;
  92.     return(dir);
  93. }
  94.  
  95. /* ====================================================================== */
  96.  
  97. void Hello(char *dir)
  98. {
  99.     printf("\2337m%s\2330m\n", HELLO);
  100.     printf("The current name directory is \"%s\"\n\n", NameDir(dir));
  101. }
  102.  
  103. /* ====================================================================== */
  104.  
  105. /* This function makes a BCPL string into a C style string. */
  106.  
  107. char *b2cstr(char *cstr, BPTR bptr) {
  108.     char *ptr = (char *)BADDR(bptr);
  109.     strncpy(cstr,ptr+1,*ptr);
  110.     cstr[*ptr] = '\0';
  111.     return cstr;       
  112. }
  113.  
  114. /* This function allocates things in a DOS friendly way. */
  115.  
  116. void *DOSAlloc(LONG size) {
  117.     LONG *ptr = AllocMem(size+4,MEMF_PUBLIC|MEMF_CLEAR);
  118.     *ptr = size+4;
  119.     return ptr+1;
  120. }
  121.  
  122. /* This function frees memory in a DOS friendly way. */
  123.  
  124. void DOSFree(void *mem) {
  125.     LONG *ptr = (LONG *)mem;
  126.     FreeMem(ptr-1,*(ptr-1));
  127. }
  128.  
  129. /* ====================================================================== */
  130.  
  131. /* Here we manage name trees.  Name nodes are built from the device list
  132.     first.  All primary nodes based on the device list have NULL paths,
  133.     indicating that they are primary and thus, don't need to be recreated.
  134.     Subsequent nodes are added to the node that they depend on.  If a node 
  135.     is encountered that doesn't have a parent listed yet, it will be place
  136.     on a temporary node list. */
  137.  
  138. struct NameNode {
  139.     struct Node node;
  140.     struct NameNode *parent;
  141.     struct List children;
  142.     char *path;
  143.     BOOL trymount;
  144. };
  145.  
  146. struct List Names;
  147. struct NameNode *lostnodes;
  148.  
  149. /* This function creates a name node, allocating whatever memory is 
  150.     needed. */
  151.  
  152. struct NameNode *MakeNode(char *name, char *path) {
  153.     struct NameNode *nn;
  154.     int pathlen;
  155.     
  156.     if (!(nn = calloc(1,sizeof(struct NameNode)))) return NULL;
  157.     if (name) nn->node.ln_Name = CopyStr(name);
  158.     NewList(&nn->children);
  159.     if (path){
  160.         pathlen = strlen(path)-1;
  161.         if (path[pathlen]=='#')
  162.             path[pathlen]='\0';
  163.         nn->path = CopyStr(path);
  164.     }
  165.     nn->trymount = FALSE;
  166.     return nn;
  167. }
  168.  
  169. /* This function finds a particular name in the Names data base, via a 
  170.     depth-first search.  If it finds the name, it returns that node, 
  171.     otherwise, it returns NULL. */
  172.  
  173. struct NameNode *FindNode(struct List *lst,char *name) {
  174.     struct Node *n;
  175.     struct NameNode *nn;
  176.     
  177.     for (n = lst->lh_Head; n->ln_Succ; n = n->ln_Succ) {
  178.         if (!(stricmp(name,n->ln_Name))) return (struct NameNode *)n;
  179.         if (nn = FindNode(&((struct NameNode *)n)->children,name)) return nn;
  180.     }
  181.     return NULL;
  182. }
  183.  
  184. /* This function prints the whole Nametree */
  185.  
  186. void PrintList(struct List* lst,char *title, UBYTE level){
  187.     struct Node *n;
  188.     struct NameNode *nn;
  189.  
  190.     if (veryverbose){
  191.         if (level==0) printf("%s\n",title);
  192.         for (n = lst->lh_Head; n->ln_Succ; n = n->ln_Succ) {
  193.             nn = (struct NameNode *)n;
  194.             printf("%s, ",nn->node.ln_Name);
  195.             if (nn->children.lh_Head->ln_Succ){
  196.                 printf("\n%*s",level+2,"");
  197.                 PrintList(&nn->children,"--",level+2);
  198.                 printf("\n%*s",level,"");
  199.             }
  200.         }    
  201.         if (level==0) printf("\n\n");
  202.     }
  203. }
  204.  
  205. /* Strip trailing and heading spaces and tabs from a string. */
  206. void StripStr(char *str)
  207. {
  208.     char *p;
  209.     int len,i,offset=0;
  210.  
  211.     /* Do nothing to NULL strings and empty strings. */
  212.     if (!str) return;
  213.  
  214.     len = strlen(str);
  215.     if (len == 0) return;
  216.  
  217.     /* How many beginning stripchars ? */
  218.     while ((str[offset] == ' ') || (str[offset] == '\t'))    offset++;
  219.  
  220.     /* Move following chars to beginning of string */
  221.     if (offset>1){    
  222.         i=0;
  223.         while (i<len-offset) str[i] = str[offset+(i++)];
  224.  
  225.         /* overwrite old end with spaces */
  226.         while (i<len) str[i++] = ' ';
  227.     }
  228.  
  229.     /* Point at last character before the NULL.  len is >= 1. */
  230.     p = str + len - 1;
  231.  
  232.     /* Skip to the point ahead of all trailing space chars. */
  233.     while ((p >= str) && (*p == ' ') || (*p == '\t')) p--;
  234.  
  235.     /* Whomp it. */
  236.     *(++p) = '\0';
  237. }
  238.  
  239. /* This is the node assignment routine.  It accepts a node name and a path
  240.     for assignment.  It handles all the proper node creations to add that
  241.     information to the node data base. */
  242.     
  243. void DefNode(char *name, char *manypath) {
  244.     struct NameNode *nn, *parent, *removed,
  245.                          *nnparent, *grandparent,
  246.                          *nnparent2;
  247.     char pardev[64], *dummy, path[64];
  248.     int i, last , pathlen;
  249.     BOOL pathisfirst;
  250.                 
  251.     for (i = 0; manypath[i] != ',' && manypath[i] != '\0' && i < 63; ++i) path[i] = manypath[i];
  252.     path[i] = '\0';
  253.     StripStr(path);
  254.  
  255.     last=i+1;
  256.     while (path[0]!='\0'){
  257.         for (i = 0; path[i] != ':' && i < 63; ++i) pardev[i] = path[i];
  258.         pardev[i] = '\0';
  259.         if (!(parent = FindNode(&Names,pardev))) {
  260.             VVERBOSE("Device '%s:' from path '%s' not found!\n",pardev,path);
  261.             AddHead(&lostnodes->children,(struct Node *)(parent=MakeNode(pardev,NULL)));
  262.             parent->trymount = TRUE;
  263.             parent->parent = parent;
  264.             PrintList(&Names,"new parent enqueued:",0);
  265.         }
  266.         
  267.         if (!(nn = FindNode(&Names,name))){
  268.             nn = MakeNode(name,path);
  269.             if (parent->trymount || parent->path)
  270.                 nn->parent = parent;
  271.             else
  272.                 nn->parent = nn;
  273.  
  274.             VVERBOSE("New node '%s:' with path '%s'\n",name,path);
  275.             AddHead(&parent->children,(struct Node *)nn);
  276.         }
  277.         else {
  278.             removed = NULL;
  279.             nnparent2 = nn;
  280.             nnparent  = nn;
  281.             do
  282.             {
  283.                 nnparent=nnparent->parent;
  284.                 grandparent=parent;
  285.                 do
  286.                 {
  287.                     grandparent=grandparent->parent;
  288.                     if (nnparent->node.ln_Name == grandparent->node.ln_Name){
  289.                         removed = nnparent2;
  290.                     }
  291.                 }while(grandparent->node.ln_Name != grandparent->parent->node.ln_Name);
  292.                 nnparent2=nnparent;
  293.             }while(nnparent->node.ln_Name != nnparent->parent->node.ln_Name);
  294.  
  295.             if (!removed) removed = nnparent;
  296.             
  297.                 if (parent->trymount || parent->path) removed->parent = parent;
  298.                 Remove((struct Node *)removed);
  299.                 VVERBOSE("Removed node: '%s:'\n",removed->node.ln_Name);
  300.                 PrintList(&Names,"removed:",0);
  301.                 AddHead(&parent->children,(struct Node *)removed);
  302.             
  303.             nn->trymount = FALSE;
  304.  
  305.             VVERBOSE("Path changed for: '%s:'\nfrom: '%s'\n",name,nn->path);
  306.             pathlen = strlen(path)-1;
  307.             if (path[pathlen]=='#'){
  308.                 path[pathlen]='\0';
  309.                 pathisfirst  = TRUE;
  310.             }
  311.             else pathisfirst = FALSE;
  312.  
  313.             if (nn->path){
  314.                 if (pathisfirst){
  315.                     dummy = CatStr(path,nn->path);
  316.                     path[pathlen]=' ';
  317.                 }
  318.                 else
  319.                     dummy = CatStr(nn->path,path);
  320.                 FreeStr(nn->path);
  321.                 nn->path = dummy;
  322.             }
  323.             else
  324.                 nn->path = CopyStr(path);
  325.                 if (pathisfirst)
  326.                     path[pathlen]=' ';
  327.             VVERBOSE("  to: '%s'\n\n",nn->path);
  328.         }
  329.         PrintList(&Names,"Node enqueued:",0);
  330.         if (manypath[last-1] != '\0'){
  331.             for (i = last; (manypath[i] != ',') && (manypath[i] != '\0') && (i-last < 63); ++i)
  332.                 path[i-last] = manypath[i];
  333.  
  334.             path[i-last] = '\0';
  335.             last = i+1;
  336.             StripStr(path);
  337.         }
  338.         else
  339.             path[0] = '\0';
  340.     }
  341. }  
  342.  
  343. /* This function reads in the individual file's data and builds entries
  344.     in the name list based on that data. */
  345.     
  346. void AddFIB(struct FileInfoBlock *fib,char *name) {  
  347.     BPTR file;
  348.     char *buf,*com,*path;
  349.         
  350.     if (buf = AllocMem(fib->fib_Size+1,0L)) {
  351.         if (file = Open(name,MODE_OLDFILE)) {
  352.             Read(file,buf,fib->fib_Size);
  353.             buf[fib->fib_Size] = '\0';
  354.             com = strtok(buf,":\t\n");
  355.             path = strtok(NULL,"\t\n");
  356.             StripStr(com);
  357.             StripStr(path);
  358.             while (com && path) {
  359.                 if (com[0] != ';')
  360.                     DefNode(com,path);
  361.  
  362.                 com = strtok(NULL,":\t\n");
  363.                 path = strtok(NULL,"\t\n");
  364.                 StripStr(com);
  365.                 StripStr(path);
  366.             }
  367.             Close(file);
  368.         }
  369.         FreeMem(buf,fib->fib_Size+1);
  370.     }
  371. }
  372.  
  373. /* ====================================================================== */
  374.  
  375. /* This function opens up the stuff we need. */
  376.         
  377. BOOL DoInits(void) {
  378.     if (!(DosBase = (struct DosLibrary *)OpenLibrary("dos.library",33L)))
  379.         return FALSE;
  380.     if (!(info = (struct DosInfo *)BADDR(((struct RootNode *)DosBase->dl_Root)->rn_Info)))
  381.         return FALSE;
  382.     if (!(fileinfo = AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC)))
  383.         return FALSE;
  384.             
  385.     return TRUE;
  386. }
  387.  
  388. /* This function cleans up after DoInits. */
  389.  
  390. void CloseUp(int code, char *str) {
  391.     if (str) printf("Error: %s\n",str);
  392.     if (fileinfo) FreeMem(fileinfo,sizeof(struct FileInfoBlock));
  393.     if (namelock) UnLock(namelock);
  394.     if (DosBase) CloseLibrary((struct Library *)DosBase);
  395.     exit(code);   
  396. }
  397.  
  398. /* ====================================================================== */
  399.  
  400. /* This function finds a directory node.  It has the side effect of
  401.     setting "lastdev" to the last device in the global device list. */
  402.  
  403. struct DeviceList *AllocDirNode(char *name) {
  404.     struct DeviceList *dev, *newdev;
  405.     char *str,old[64];
  406.  
  407.     /* Let's see if the assignment has already been made... */
  408.     for (dev = (struct DeviceList *)BADDR(info->di_DevInfo); dev != NULL; 
  409.             dev = (struct DeviceList *)BADDR(dev->dl_Next)) {
  410.         lastdev = dev;
  411.         if (dev->dl_Type != DLT_DIRECTORY) continue;
  412.         b2cstr(old,dev->dl_Name);
  413.         if (!stricmp(old,name))
  414.             return dev;
  415.     }
  416.  
  417.     /* Create the new name structure */
  418.     if (!(newdev=DOSAlloc(sizeof(struct DeviceList))) || !(str=DOSAlloc(32L))) {
  419.         if (newdev) DOSFree(newdev);
  420.         return NULL;
  421.     }
  422.     newdev->dl_Type = DLT_DIRECTORY;
  423.     strcpy(str+1,name);
  424.     str[0] = strlen(name);
  425.     newdev->dl_Name = CADDR(str);
  426.     return newdev;
  427. }
  428.  
  429. /* This function does the "Assign" operation. */
  430.  
  431. BOOL Assign(char *name, char *path) {
  432.     BPTR block;
  433.     struct DeviceList *newdev;
  434.     char old[64], *pathpart;
  435.     BOOL oldchanged = FALSE;
  436.  
  437.     pathpart = strtok(path, ",");
  438.  
  439.     /* Let's verify that the path object is really there.  If not, try to make
  440.         the thing. */
  441.     if (!(block = Lock(pathpart,SHARED_LOCK))) {
  442.         if (!(block = CreateDir(pathpart))) return FALSE;
  443.         UnLock(block);
  444.         if (!(block = Lock(pathpart,SHARED_LOCK))) return FALSE;
  445.     }
  446.  
  447.     /* Get a node for this assignment. */
  448.     Forbid();
  449.     newdev = AllocDirNode(name);
  450.  
  451.     /* Make the assignment */
  452.     if (newdev->dl_Lock) {
  453.         Permit();
  454.         UnLock(newdev->dl_Lock);
  455.         oldchanged = TRUE;
  456.         VVERBOSE("Changing old assign '%s:' to '%s'\n",b2cstr(old, newdev->dl_Name),pathpart);
  457.     }
  458.     newdev->dl_Lock = block;
  459.     newdev->dl_Task = ((struct FileLock *)BADDR(block))->fl_Task;
  460.  
  461.     if (!oldchanged){
  462.         /* Now link it into the device list. */
  463.         newdev->dl_Next = lastdev->dl_Next;
  464.         lastdev->dl_Next = CADDR(newdev);
  465.         Permit();
  466.     }
  467.  
  468.     pathpart = strtok(NULL, ",");
  469.     while (pathpart && adding){
  470.         VVERBOSE("Adding '%s' to '%s:' ",pathpart,name);
  471.  
  472.         /* Let's verify that the path object is really there.  If not, try to make
  473.             the thing. */
  474.         if (!(block = Lock(pathpart,SHARED_LOCK))) {
  475.             if (!(block = CreateDir(pathpart))){
  476.                 VVERBOSE("failed!! (CreateDir)\n");
  477.                 return FALSE;
  478.             }
  479.             UnLock(block);
  480.             if (!(block = Lock(pathpart,SHARED_LOCK))){
  481.                 VVERBOSE("failed!! (LockDir)\n");
  482.                 return FALSE;
  483.             }
  484.         }
  485.         if (RemAssignList(name,block))
  486.             VVERBOSE("(old multiassign removed) ");
  487.  
  488.         if (!AssignAdd(name, block))
  489.             VVERBOSE("failed!!");
  490.  
  491.         VVERBOSE("\n");
  492.  
  493.         pathpart = strtok(NULL, ",");
  494.     }
  495.  
  496.     return TRUE;
  497. }
  498.  
  499. /* This list takes in a node list, and performs assignments for all non-primary
  500.     nodes in the list, as long as "test" is FALSE. */
  501.  
  502. void AssignList(struct List *lst, int level) {
  503.     struct Node *n;
  504.     struct NameNode *nn;
  505.     char     *command = "c:Mount ",
  506.             *commandstr;
  507.     long     result = 0;
  508.     BOOL     dummytest = test,
  509.             dummyverbose = verbose;
  510.     
  511.     for (n = lst->lh_Head; n->ln_Succ; n = n->ln_Succ) {
  512.         nn = (struct NameNode *)n;
  513.         if (nn->path) {
  514.             VERBOSE("%*s%-20s%*s%s\2330m\n",level+1,"\23333m",nn->node.ln_Name,
  515.                          14-level,"\23332m",nn->path);
  516.             if (!test) Assign(nn->node.ln_Name,nn->path);
  517.         }
  518.         else if (nn->trymount){
  519.             STags[0].ti_Tag = SYS_Input; STags[0].ti_Data = Input(); 
  520.             STags[1].ti_Tag = SYS_Output; STags[1].ti_Data = Output(); 
  521.             STags[2].ti_Tag = SYS_Asynch; STags[2].ti_Data = FALSE; 
  522.             STags[3].ti_Tag = TAG_DONE;
  523.             commandstr = CatCom(command,nn->node.ln_Name);
  524.             if (!test) result = SystemTagList(commandstr,STags);
  525.             VVERBOSE("Mounting '%s', result = %d\n",nn->node.ln_Name,result);
  526.             if (result != 0){
  527.                 test    = TRUE;
  528.                 verbose = TRUE;
  529.                 printf("Warning: Can't Resolve Names:\n");
  530.             }
  531.             else
  532.                 VERBOSE("Assigned Names:\n");
  533.         }
  534.         if (nn->children.lh_Head->ln_Succ) 
  535.             AssignList(&nn->children,level+2);
  536.  
  537.         test    = dummytest;
  538.         verbose = dummyverbose;
  539.     }
  540. }
  541.  
  542. /* ====================================================================== */
  543.  
  544. void main(int argc, char *argv[]) {
  545.     char path[256], *dir = NULL;
  546.     long i;
  547.     struct NameNode *nn;
  548.     struct DeviceList *dev;
  549.     BOOL die = FALSE;
  550.  
  551.     if (!DoInits()) CloseUp(5,NULL);
  552.  
  553.     /* Check the command line. */
  554.     for (i = 1; i < argc; ++i)
  555.         switch (toupper(argv[i][0])) {
  556.             case 'S':
  557.                 Assign("SYS",argv[++i]);
  558.                 break;
  559.             case 'D':
  560.                 dir = argv[++i];
  561.                 break;
  562.             case 'V':
  563.                 verbose = TRUE;
  564.                 if (toupper(argv[i][1])=='V')
  565.                     veryverbose = TRUE;
  566.                 break;
  567.             case 'T':
  568.                 test = TRUE;
  569.                 verbose = TRUE;
  570.                 break;
  571.             case 'N':
  572.                 adding = FALSE;
  573.                 break;
  574.             case '?':
  575.                 die = TRUE;
  576.                 break;
  577.         }
  578.  
  579.     if (die)
  580.     {
  581.     Hello(dir);
  582.     printf("Usage: %s [[V]VERBOSE] [TEST] [NOADD] [DIR <namesdir>] [SYSTEM drive]\n", 
  583.                 argv[0]);
  584.             CloseUp(0,NULL);
  585.     }
  586.  
  587.     if (verbose) Hello(dir);
  588.  
  589.     if (adding && (SysBase->lib_Version<36)){
  590.         printf("Error: Release 2 (V36) or a later version of the OS is required for AssignAdds.\n");
  591.         adding = FALSE;
  592.     }
  593.  
  594.     /* Let's build the internal device list.  We know this list is going to be
  595.         a flat list; everything is primary, and thus hung from the root list. */
  596.     NewList(&Names);
  597.     Forbid();
  598.     for (dev = (struct DeviceList *)BADDR(info->di_DevInfo); dev != NULL; 
  599.             dev = (struct DeviceList *)BADDR(dev->dl_Next)) {
  600.         if (!(nn = MakeNode(b2cstr(path,dev->dl_Name),NULL)))
  601.             continue;
  602.         nn->parent = nn;
  603.         AddHead(&Names,(struct Node *)nn);
  604.     }
  605.     Permit();
  606.     
  607.     /* I need to build the "lostnodes" node.  In order to avoid name collisions,
  608.         I make the name of this node '\0'.  We never need to search for it by
  609.         name... */
  610.  
  611.     AddTail(&Names,(struct Node *)(lostnodes = MakeNode("\0",NULL)));
  612.     PrintList(&Names,"System List:",0);
  613.         
  614.     /* Here I build the list of required assignments by walking through the
  615.         SYS:Names directory, and reading each file. */
  616.   
  617.         if ((namelock = Lock(NameDir(dir),SHARED_LOCK))) {
  618.         Examine(namelock,fileinfo);
  619.         while (ExNext(namelock,fileinfo) || IoErr() != ERROR_NO_MORE_ENTRIES) {
  620.             if (fileinfo->fib_DirEntryType > 0) continue;
  621.             strcat(strcat(strcpy(path,NameDir(dir)),"/"),fileinfo->fib_FileName);
  622.             AddFIB(fileinfo,path);
  623.         }
  624.     }
  625.  
  626.     /* Now I've got everything; let's see what's actually here. */
  627.   
  628.     /* Remove((struct Node *)lostnodes);*/
  629.  
  630.     VERBOSE("Assigned Names:\n");
  631.     AssignList(&Names,1);
  632.     CloseUp(0,NULL);
  633. }
  634.